//数据包格式buf[1024]
//第1、2位为head: buf[0]为约车人的请求
//		  buf[1]为出租车的请求
//	具体值为: 2 注册
//		  3 登录
//		  4 退出
//		  5 上传我的位置
//		  6 开启UDP，获取ip
//		  7 心跳包
//		  8 约车/同意约车
//		  9 约车信息（服务器发送三个信息）
//第3~6位为len: buf[2]~buf[5]
//第7～1024位为数据

#include <sys/types.h>       
#include<stdio.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <sys/epoll.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<math.h>
#include <ifaddrs.h>
#include<ctype.h>

#define REGIST '2'
#define LOGIN  '3'
#define LOGOUT '4'
#define GPS    '5'
#define UDP_IP '6'
#define HEART  '7'
#define ASK_AN '8'
#define GINFO  '9'

#define CARPATH "car_info.log"
#define MANPATH "man_info.log"


typedef struct client_data{
    struct sockaddr_in *cin;
    char buf[1024];
    int *cfd;
    int *epoll_instance;
    struct epoll_event *events;


}DATA;


typedef struct p_info_live
{
    char user_name[21];
    char pass_word[21];
    char money[5];
    char online[5];
    char empty[5];
    char X[5];
    char Y[5];
    char ip[16];
    char udp_port[7];
    char soure[60];
    char dest[60];
    int port;
    int heart_time;
    struct p_info_live *next;
}P_INFO_LIVE;

typedef struct p_info
{
    char user_name[21];
    char pass_word[21];
    char money[5];
    struct p_info *next;
}P_INFO;

typedef struct info
{
    char user_name[21];
    char pass_word[21];
    char money[5];
}INFO;


P_INFO_LIVE *head_car_live=NULL;
P_INFO_LIVE *head_man_live=NULL;

P_INFO *head_car=NULL;
P_INFO *head_man=NULL;




void GetGateWay(char gateway[])  
{  
    FILE *fp;  
    char buf[512];  
    char cmd[128]; 
    char *tmp;  

    strcpy(cmd, "ip route");  
    fp = popen(cmd, "r"); 
    if(NULL == fp)  
    {  
	perror("popen error");  
	return ;  
    }  
    while(fgets(buf, sizeof(buf), fp) != NULL)  
    {  
	tmp =buf;  
	while(*tmp && isspace(*tmp))  
	    ++ tmp;  
	if(strncmp(tmp, "default", strlen("default")) == 0)  
	    break;  
    }  
    sscanf(buf, "%*s%*s%s", gateway);         
    printf("服务器网关:%s\n", gateway);  
    pclose(fp);  
}  



void Get_IP_addr (char ip_address[])
{
    struct ifaddrs * ifAddrStruct=NULL;
    void * tmpAddrPtr=NULL;

    char gateway[30];  
    getifaddrs(&ifAddrStruct);

 
    GetGateWay(gateway);
    
    while (ifAddrStruct!=NULL) 
    {
	if (ifAddrStruct->ifa_addr->sa_family==AF_INET)
	{   // check it is IP4
	    // is a valid IP4 Address
	    tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
	    char addressBuffer[INET_ADDRSTRLEN];
	    inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
	    if(0==strncmp(gateway,addressBuffer,12))
	    {
		printf("网卡标识:%s\n服务器IP地址:%s\n", ifAddrStruct->ifa_name, addressBuffer); 
		strcpy(ip_address,addressBuffer);
		break;
	    }
	}
	ifAddrStruct=ifAddrStruct->ifa_next;
    }

//    return 0;
}



void * heart_time_pack(void*i)
{
    P_INFO_LIVE *p_car_live;
    P_INFO_LIVE *p_car_live_before;

    P_INFO_LIVE *p_man_live;
    P_INFO_LIVE *p_man_live_before;
    while(1)
    {
	sleep(6);

	p_car_live=head_car_live->next;
	p_car_live_before=head_car_live;

	p_man_live=head_man_live->next;
	p_man_live_before=head_man_live;

	while(p_car_live)
	{
	    if(p_car_live->heart_time<0)
	    {
		(*(int*)i)--;
		p_car_live_before->next=p_car_live->next;
		free(p_car_live);
		p_car_live=p_car_live_before->next;
	    }
	    else
	    {
		p_car_live->heart_time--;
		p_car_live=p_car_live->next;
		p_car_live_before=p_car_live_before->next;
	    }
	}
	while(p_man_live)
	{
	    if(p_man_live->heart_time<0)
	    {
		(*(int*)i)--;
		p_man_live_before->next=p_man_live->next;
		free(p_man_live);
		p_man_live=p_man_live_before->next;
	    }
	    else
	    {
		p_man_live->heart_time--;
		p_man_live=p_man_live->next;
		p_man_live_before=p_man_live_before->next;
	    }
	}
    }
    return i;

}

void save_info(char *PATH,P_INFO *head)//保存信息至文件
{ 
    INFO write_info ;

    FILE *save_f;

    P_INFO *p;

    p=head->next;

    save_f=fopen(PATH,"w");//读取已有帐号和密码保存的文件
    fclose(save_f);

    while(p)//循环读取结构体的帐号和密码，读完整个文件退出循环
    {

	save_f=fopen(PATH,"a");

	strcpy(write_info.pass_word,p->pass_word);
	strcpy(write_info.user_name,p->user_name);
	strcpy(write_info.money,p->money);

	fwrite(&write_info,sizeof(INFO),1,save_f);

	p=p->next;
	fclose(save_f);
    }
}


void int_to_str(int i,char s[])
{
    int a,b;
    char c,d;
    memset(s,0,2);
    a=i/10;
    b=i%10;
    c='0'+a;
    d='0'+b;
    strncpy(s,&c,1);
    strncat(s,&d,1);
}


void sort_XY(P_INFO_LIVE**head,int X,int Y)
{
    //将head取出最高尾插到head_sore

    //*****************排序计算开始**************************//
    
    int max;

    P_INFO_LIVE *p_new,*tmp_p,*free_p,*p_sore,*p;

    P_INFO_LIVE *head_sore=NULL;
    head_sore=malloc(sizeof(P_INFO_LIVE));
    memset(head_sore,0,sizeof(P_INFO_LIVE));


    p=*head;
    p=p->next;
    p_sore=head_sore;

    while((*head)->next)
    {
	p_new=malloc(sizeof(P_INFO_LIVE));
	memset(p_new,0,sizeof(P_INFO_LIVE));
	p=(*head)->next;

	max=-1;
	while(p)
	{
	    if(max<=(int)(sqrt((atoi(p->X)-X)*(atoi(p->X)-X)+(atoi(p->Y)-Y)*(atoi(p->Y)-Y))))
	    {
		max=(int)sqrt((atoi(p->X)-X)*(atoi(p->X)-X)+(atoi(p->Y)-Y)*(atoi(p->Y)-Y));

		strcpy(p_new->user_name,p->user_name);
		strcpy(p_new->pass_word,p->pass_word);
		strcpy(p_new->X,p->X);
		strcpy(p_new->Y,p->Y);
		strcpy(p_new->ip,p->ip);
		strcpy(p_new->empty,p->empty);
		strcpy(p_new->online,p->online);
		strcpy(p_new->money,p->money);
		strcpy(p_new->udp_port,p->udp_port);
		strcpy(p_new->soure,p->soure);
		strcpy(p_new->dest,p->dest);
		p_new->heart_time=p->heart_time;
		p_new->port=p->port;

	    }

	    p=p->next;
	}

	free_p=(*head)->next;
	tmp_p=*head;

	while(free_p)
	{
	    if(0==strcmp(p_new->user_name,free_p->user_name))
	    {
		break;
	    }
	    tmp_p=tmp_p->next;
	    free_p=free_p->next;
	}

	tmp_p->next=free_p->next;

	free(free_p);

	p_new->next=p_sore->next;
	p_sore->next=p_new;
//	p_sore=p_sore->next;	//头插,使用结果:递减排序				
    }

//****************排序结束***************************//
    *head=head_sore;

#if 0  //打印链表内容 
    *head=head_sore;
    p=*head;
    p=p->next;
    while(p)
    {
	printf("p->user_name=%s\n",p->user_name);
	printf("p->pass_word=%s\n",p->pass_word);
	printf("p->money=%s\n",p->money);
	printf("p->online=%s\n",p->online);
	printf("p->empty=%s\n",p->empty);
	printf("p->ip=%s\n",p->ip);
	printf("p->X=%s\n",p->X);
	printf("p->Y=%s\n",p->Y);
	printf("p->udp_port=%s\n",p->udp_port);
	printf("p->soure=%s\n",p->soure);
	printf("p->dest=%s\n",p->dest);
	printf("p->port=%d\n",p->port);
	printf("p->heart_time=%d\n",p->heart_time);

	p=p->next;
    }
#endif

}

void send_error(char buf[])
{

    strcpy(buf,"ErrorRequired");
}


void user_info(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	int i=0;
	int far;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;

	int X;
	int Y;


	strncpy(nlen,&d->buf[6+name_len+pass_len],2);
	X=atoi(nlen)*100;
	strncpy(nlen,&d->buf[6+name_len+pass_len+2],2);
	X=X+atoi(nlen);

	strncpy(plen,&d->buf[6+name_len+pass_len+4],2);
	Y=atoi(plen)*100;
	strncpy(plen,&d->buf[6+name_len+pass_len+6],2);
	Y=Y+atoi(plen);

	sort_XY(&head_man_live,X,Y);//对在线约车人排序

	memset(d->buf,0,1024);
	strncpy(&d->buf[0],"09",2);
	
	p=head_man_live->next;

	while(p)
	{
	    if(0==strncmp(p->empty,"free",4)&&0==strncmp(p->online,"onli",4))
	    {
		int_to_str(strlen(p->user_name),nlen);
		strncat(d->buf,nlen,2);
		strncat(d->buf,p->user_name,strlen(p->user_name));
		far=(int)sqrt((atoi(p->X)-X)*(atoi(p->X)-X)+(atoi(p->Y)-Y)*(atoi(p->Y)-Y));
		int_to_str(far/100,nlen);
		strncat(d->buf,nlen,2);
		int_to_str(far%100,nlen);
		strncat(d->buf,nlen,2);

		int_to_str(strlen(p->soure),nlen);//添加出发地和目的地
		strncat(d->buf,nlen,2);
		int_to_str(strlen(p->dest),nlen);
		strncat(d->buf,nlen,2);

		strncat(d->buf,p->soure,strlen(p->soure));
		strncat(d->buf,p->dest,strlen(p->dest));



		if(i>=2)break;
		else i++;
	    }
	    p=p->next;
	}
	strncat(d->buf,"0000",4);
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	int i=0;
	int far;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;

	int X;
	int Y;

	
	strncpy(nlen,&d->buf[6+name_len+pass_len],2);
	X=atoi(nlen)*100;
	strncpy(nlen,&d->buf[6+name_len+pass_len+2],2);
	X=X+atoi(nlen);

	strncpy(plen,&d->buf[6+name_len+pass_len+4],2);
	Y=atoi(plen)*100;
	strncpy(plen,&d->buf[6+name_len+pass_len+6],2);
	Y=Y+atoi(plen);

	sort_XY(&head_car_live,X,Y);//对在线出租车距离排序

	memset(d->buf,0,1024);
	strncpy(&d->buf[0],"90",2);
	
	p=head_car_live->next;

	while(p)
	{
	    if(0==strncmp(p->empty,"free",4)&&0==strncmp(p->online,"onli",4))
	    {
		int_to_str(strlen(p->user_name),nlen);
		strncat(d->buf,nlen,2);
		strncat(d->buf,p->user_name,strlen(p->user_name));
		far=(int)sqrt((atoi(p->X)-X)*(atoi(p->X)-X)+(atoi(p->Y)-Y)*(atoi(p->Y)-Y));
		int_to_str(far/100,nlen);
		strncat(d->buf,nlen,2);
		int_to_str(far%100,nlen);
		strncat(d->buf,nlen,2);

		if(i>=2)break;
		else i++;
	    }
	    p=p->next;
	}
	strncat(d->buf,"0000",4);
    }
}


void deel_ask(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	int ulen;
	char nlen[3]={0};
	char plen[3]={0};
	char uname[21]={0};

	char cname[21]={0};
	char cpass[21]={0};

	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	
	name_len =atoi(nlen);
	pass_len =atoi(plen);

	strncat(cname,&d->buf[6],name_len);
	strncat(cpass,&d->buf[6+name_len],pass_len);

	strncpy(nlen,&d->buf[6+name_len+pass_len],2);
	ulen = atoi(nlen);

	strncpy(uname,&d->buf[6+name_len+pass_len+2],ulen);

	memset(d->buf,0,1024);
	strncpy(d->buf,"06",2);
	strncat(d->buf,cname,name_len);
	strncat(d->buf,cpass,pass_len);

	P_INFO_LIVE *p;
	p=head_man_live;
	while(p)
	{
	    if(0==strncmp(p->user_name,uname,ulen)&&0==strncmp(p->online,"onli",4)&&0==strncmp(p->empty,"free",4))
	    {
		strncat(d->buf,p->ip,strlen(p->ip));
	//	strncpy(p->empty,"full",4);//约的时候将对方状态锁定，不给别人联系
		break;
	    }
	    p=p->next;
	}
	strncat(d->buf,"XXXX",4);
	strncat(d->buf,p->udp_port,6);
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	int ulen;
	char nlen[3]={0};
	char plen[3]={0};
	char uname[21]={0};

	char cname[21]={0};
	char cpass[21]={0};

	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	
	name_len =atoi(nlen);
	pass_len =atoi(plen);

	strncat(cname,&d->buf[6],name_len);
	strncat(cpass,&d->buf[6+name_len],pass_len);

	strncpy(nlen,&d->buf[6+name_len+pass_len],2);
	ulen = atoi(nlen);

	strncpy(uname,&d->buf[6+name_len+pass_len+2],ulen);

	memset(d->buf,0,1024);
	strncpy(d->buf,"60",2);
	strncat(d->buf,cname,name_len);
	strncat(d->buf,cpass,pass_len);

	P_INFO_LIVE *p;
	p=head_car_live;
	while(p)
	{
	    if(0==strncmp(p->user_name,uname,ulen)&&0==strncmp(p->online,"onli",4)&&0==strncmp(p->empty,"free",4))
	    {
		strncat(d->buf,p->ip,strlen(p->ip));
	//	strncpy(p->empty,"full",4);//约的时候将对方状态锁定，不给别人联系
		break;
	    }
	    p=p->next;
	}
	strncat(d->buf,"XXXX",4);
	strncat(d->buf,p->udp_port,6);
    }
}

void heart_pack(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	P_INFO_LIVE *p;
	p=head_car_live;
	while(p)
	{
	    if(p->port==ntohs(d->cin->sin_port))
	    {
		p->heart_time=2;
		return ;
	    }
	    p=p->next;
	}
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	P_INFO_LIVE *p;
	p=head_man_live;
	while(p)
	{
	    if(p->port==ntohs(d->cin->sin_port))
	    {
		p->heart_time=2;
		return ;
	    }
	    p=p->next;
	}
    }
}

void udp_ip(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	P_INFO_LIVE *p;
	p=head_car_live;
	while(p)
	{
	    if(p->port==ntohs(d->cin->sin_port))//检查在线用户中的端口匹配
	    {
		strncpy(p->empty,&d->buf[2],4);
	//	printf("car->empty=%s\n",p->empty);

		break;
	    }
	    p=p->next;
	}
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	P_INFO_LIVE *p;
	p=head_man_live;
	while(p)
	{
	    if(p->port==ntohs(d->cin->sin_port))//检查在线用户中的端口匹配
	    {
		strncpy(p->empty,&d->buf[2],4);
	//	printf("man->empty=%s\n",p->empty);

		break;
	    }
	    p=p->next;
	}
    }

}

void update_gps(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;
	p=head_car_live;
	while(p)
	{
	    if(0==strncmp(p->user_name,&d->buf[6],name_len)&&0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len))
	    {
		strncpy(p->online,"onli",4);
		strncpy(p->X,&d->buf[6+name_len+pass_len],4);
		strncpy(p->Y,&d->buf[6+name_len+pass_len+4],4);
		strncpy(p->udp_port,&d->buf[6+name_len+pass_len+4+4+4],6);//端口

		strncpy(p->empty,"free",4);

		break;
	    }
	    p=p->next;
	}
	user_info(d);
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	char slen[3]={0};
	char tlen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;
	p=head_man_live;
	while(p)
	{
	    if(0==strncmp(p->user_name,&d->buf[6],name_len)&&0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len))
	    {
		strncpy(p->online,"onli",4);
		strncpy(p->X,&d->buf[6+name_len+pass_len],4);
		strncpy(p->Y,&d->buf[6+name_len+pass_len+4],4);
		strncpy(p->udp_port,&d->buf[6+name_len+pass_len+4+4+4],6);//端口
		
		strncpy(slen,&d->buf[6+name_len+pass_len+4+4+4+6],2);
		strncpy(tlen,&d->buf[6+name_len+pass_len+4+4+4+6+2],2);
		memset(p->soure,0,60);
		strncpy(p->soure,&d->buf[6+name_len+pass_len+4+4+4+6+2+2],atoi(slen));
		memset(p->dest,0,60);
		strncpy(p->dest,&d->buf[6+name_len+pass_len+4+4+4+6+2+2+atoi(slen)],atoi(slen));
		
//		write(1,&d->buf[6+name_len+pass_len+4+4+4],6);
		strncpy(p->empty,"free",4);

		break;
	    }
	    p=p->next;
	}
	user_info(d);
    }
}

void logout_user(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;
	P_INFO_LIVE *p_free;

	p_free=head_car_live;
	p=head_car_live->next;
	if(0==strncmp("byebye",&d->buf[6+name_len+pass_len],6))
	{
	    while(p)
	    {
		if(0==strncmp(p->user_name,&d->buf[6],name_len)&&0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len))
		{
		    strncpy(p->online,"dead",4);
		    strncpy(p->empty,"full",4);

		    p_free->next=p->next;//从在线链表中删除该用户
		    free(p);//释放节点

		    break;
		}
		p_free=p_free->next;
		p=p->next;
	    }
	    strncpy(d->buf,"goodbyeok",9);
	}
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	P_INFO_LIVE *p;
	P_INFO_LIVE *p_free;

	p_free=head_man_live;
	p=head_man_live->next;
	if(0==strncmp("byebye",&d->buf[6+name_len+pass_len],6))
	{
	    while(p)
	    {
		if(0==strncmp(p->user_name,&d->buf[6],name_len)&&0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len))
		{
		    strncpy(p->online,"dead",4);
		    strncpy(p->empty,"full",4);
		    
		    p_free->next=p->next;//从在线链表中删除该用户
		    free(p);//释放节点
		    
		    break;
		}
		p_free=p_free->next;
		p=p->next;
	    }
	    strncpy(d->buf,"goodbyeok",9);
	}
    }
}

void login_user(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	
	P_INFO *p;
	p=head_car->next;

	P_INFO_LIVE *p_live;
	P_INFO_LIVE *p_live_new;

	p_live=head_car_live->next;

	while(p_live)//匹配在线的用户
	{
	    if(0==strncmp(p_live->user_name,&d->buf[6],name_len))
	    {
		break;
	    }
	    p_live=p_live->next;	    
	}
	if(!p_live)//为NULL说明该用户名不在线,可以登录
	{
	    while(p)
	    {
		if(0==strncmp(p->user_name,&d->buf[6],name_len)&&0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len))
		{
		    strncat(d->buf,"loginok",7);
		    strncat(d->buf,p->money,4);

		    p_live_new=malloc(sizeof(P_INFO_LIVE));
		    memset(p_live_new,0,sizeof(P_INFO_LIVE));

		    strncpy(p_live_new->user_name,p->user_name,name_len);
		    strncpy(p_live_new->pass_word,p->pass_word,pass_len);
		    strncpy(p_live_new->money,p->money,4);
		    strncpy(p_live_new->online,"onli",4);
		    strncpy(p_live_new->ip,inet_ntoa(d->cin->sin_addr),strlen(inet_ntoa(d->cin->sin_addr)));
		    p_live_new->port=ntohs(d->cin->sin_port);
		    p_live_new->heart_time=1;

		    p_live=head_car_live;

		    p_live_new->next=p_live->next;//添加到头位置
		    p_live->next=p_live_new;

		    break;
		}
		p=p->next;
	    }
	    if(!p)//为NULL说明匹配不到用户名，不存在用户，登录失败
	    {
		strncat(d->buf,"fail",4);
	    }
	}
	else strncat(d->buf,"fail",4);
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);

	P_INFO *p;
	p=head_man->next;

	P_INFO_LIVE *p_live;
	P_INFO_LIVE *p_live_new;

	p_live=head_man_live->next;

	while(p_live)//匹配在线的用户
	{
	    if(0==strncmp(p_live->user_name,&d->buf[6],name_len))
	    {
		break;
	    }
	    p_live=p_live->next;	    
	}
	if(!p_live)//为NULL说明该用户名不在线,可以登录
	{
	    while(p)
	    {
		if((0==strncmp(p->user_name,&d->buf[6],name_len))&&(0==strncmp(p->pass_word,&d->buf[6+name_len],pass_len)))
		{
		    strncat(d->buf,"loginok",7);
		    strncat(d->buf,p->money,4);

		    p_live_new=malloc(sizeof(P_INFO_LIVE));
		    memset(p_live_new,0,sizeof(P_INFO_LIVE));

		    strncpy(p_live_new->user_name,p->user_name,name_len);
		    strncpy(p_live_new->pass_word,p->pass_word,pass_len);
		    strncpy(p_live_new->money,p->money,4);
		    strncpy(p_live_new->online,"onli",4);
		    strncpy(p_live_new->ip,inet_ntoa(d->cin->sin_addr),strlen(inet_ntoa(d->cin->sin_addr)));
		    p_live_new->port=ntohs(d->cin->sin_port);
		    p_live_new->heart_time=1;

		    p_live=head_man_live;

		    p_live_new->next=p_live->next;//添加到头位置
		    p_live->next=p_live_new;

		    break;
		}
		p=p->next;
	    }
	    if(!p)
	    {
		strncat(d->buf,"fail",4);
	    }
	}
	else strncat(d->buf,"fail",4);
    }
}

void regist_user(DATA*d)
{
    if(0==strncmp("0",d->buf,1))//比较第1位，为0则是出租车
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	
	P_INFO *p;
	P_INFO *p_new;

	p=head_car;
	p=p->next;

	while(p)
	{
	    if(0==strncmp(p->user_name,&d->buf[6],name_len))
	    {
		strncat(d->buf,"registfail",10);
		break;
	    }
	    p=p->next;
	}
	if(!p)
	{
	    p=head_car;
	    while(p->next)
	    {
		p=p->next;
	    }
	    p_new=malloc(sizeof(P_INFO));
	    memset(p_new,0,sizeof(P_INFO));
	    strncpy(p_new->user_name,&d->buf[6],name_len);
	    strncpy(p_new->pass_word,&d->buf[6+name_len],pass_len);
	    strcpy(p_new->money,"0000");

	    p_new->next=NULL;
	    p->next=p_new;
	    strncat(d->buf,"registok",8);

	    save_info(CARPATH,head_car);
	}
    }
    else if(0==strncmp("0",&d->buf[1],1))//比较第2位，为0则是约车人
    {
	int name_len;
	int pass_len;
	char nlen[3]={0};
	char plen[3]={0};
	strncat(nlen,&d->buf[2],2);
	strncat(plen,&d->buf[4],2);
	name_len =atoi(nlen);
	pass_len =atoi(plen);
	
	P_INFO *p;
	P_INFO *p_new;

	p=head_man;
	p=p->next;
	
	while(p)
	{
	    if(0==strncmp(p->user_name,&d->buf[6],name_len))
	    {
		strncat(d->buf,"registfail",10);
		break;
	    }
	    p=p->next;
	}
	if(!p)
	{
	    p=head_man;
	    while(p->next)
	    {
		p=p->next;
	    }
	    p_new=malloc(sizeof(P_INFO));
	    memset(p_new,0,sizeof(P_INFO));
	    strncpy(p_new->user_name,&d->buf[6],name_len);
	    strncpy(p_new->pass_word,&d->buf[6+name_len],pass_len);
	    strcpy(p_new->money,"0000");

	    p_new->next=NULL;
	    p->next=p_new;
	    strncat(d->buf,"registok",8);

	    save_info(MANPATH,head_man);
	}
    }
}


void read_data_from_client(DATA*d)
{
    if(0==strncmp(d->buf,"0",1))
    {
	switch (d->buf[1])
	{
	    case REGIST:regist_user(d);break;
	    case LOGIN :login_user(d);break;
	    case LOGOUT:logout_user(d);break;
	    case GPS   :update_gps(d);break;
	    case UDP_IP:udp_ip(d);break;
	    case HEART :heart_pack(d);break;
	    case ASK_AN:deel_ask(d);break;
	    case GINFO :user_info(d);break;
	    default    :send_error(d->buf);
	}
    }
    else if(0==strncmp(&d->buf[1],"0",1))
    {
	switch (d->buf[0])
	{
	    case REGIST:regist_user(d);break;
	    case LOGIN :login_user(d);break;
	    case LOGOUT:logout_user(d);break;
	    case GPS   :update_gps(d);break;
	    case UDP_IP:udp_ip(d);break;
	    case HEART :heart_pack(d);break;
	    case ASK_AN:deel_ask(d);break;
	    case GINFO :user_info(d);break;
	    default    :send_error(d->buf);
	}
    }
}

void deel_index(DATA*d)
{
	if(0==strncmp(&d->buf[2],"heartpack",9))
	{
	    write(1,"收到心跳包：",18);
	    write(1,d->buf,strlen(d->buf));//显示收到内容
	    write(1,"\n",1);

	}
	else
	{
	    write(1,"收到请求：",15);
	    write(1,d->buf,strlen(d->buf));//显示收到内容
	    write(1,"\n",1);
	}

    if(0==strncmp(d->buf,"3",1)||0==strncmp(d->buf,"2",1)||0==strncmp(&d->buf[1],"3",1)||0==strncmp(&d->buf[1],"2",1)||0==strncmp(d->buf,"4",1)||0==strncmp(&d->buf[1],"4",1))
    {
	read_data_from_client((DATA*)d);//处理客户端请求

	write(1,"发送内容：",15);
	write(1,d->buf,1024);//显示发送的内容
	write(1,"\n",1);

	write(*(d->cfd),d->buf,strlen(d->buf));//发送给客户端
    }
    else
    {
	P_INFO_LIVE *p;
	p=head_car_live;

	while(p)
	{
	    if(p->port==ntohs(d->cin->sin_port))//检查在线用户中的端口匹配
	    {
		p->heart_time=2;
		break;
	    }
	    p=p->next;
	}
	if(!p)//p为NULL，匹配出租车失败，客户端不在在线用户中，需要重新登录,忽略发来的请求
	{
	    p=head_man_live;

	    while(p)
	    {
		if(p->port==ntohs(d->cin->sin_port))//检查在线用户中的端口匹配
		{
		    p->heart_time=2;
		    break;
		}
		p=p->next;
	    }
	    if(!p)//p为NULL，匹配约车人失败，客户端不在在线用户中，需要重新登录,忽略发来的请求
	    {
		write(1,"忽略了客户端请求",24);
		write(1,"\n",1);
		return ;
	    }
	}
	
	if(0==strncmp(d->buf,"06",2)||(0==strncmp(d->buf,"60",2)))
	{
	    read_data_from_client((DATA*)d);//处理客户端请求
	}
	else
	{
	    read_data_from_client((DATA*)d);//处理客户端请求
	    if(0==strncmp(&d->buf[2],"heartpack",9))return;
	    write(1,"发送内容：",15);
	    write(1,d->buf,1024);//显示发送的内容
	    write(1,"\n",1);

	    write(*(d->cfd),d->buf,strlen(d->buf));//发送给客户端
	}
    }
}

void* do_for_client(void *d )
{
    deel_index((DATA*)d);
    return d;
}

void link_info(char *PATH,P_INFO **head)
{
    FILE *fp;
    int flag;
    int next_p=0;

    INFO get_info;

    P_INFO *p;
    P_INFO *p_new;

    *head =malloc(sizeof(P_INFO));
    memset(*head,0,sizeof(P_INFO));
    
    p=(*head);

    fp = fopen(PATH,"r");

    if(fp==NULL)
    {
	perror("fopen");
	fp =fopen(PATH,"w");
	fclose(fp);
	fp=fopen(PATH,"r");
    }

    while(1)//循环读取结构体的帐号和密码，读完整个文件退出循环
    {
	fseek(fp,next_p*sizeof(INFO),SEEK_SET);
	flag=fread(&get_info,sizeof(INFO),1,fp);

	if(flag)//访问结构体成功，结构体有内容
	{
	    next_p++;
	    p_new=malloc(sizeof(P_INFO));
	    memset(p_new,0,sizeof(P_INFO));

	    strcpy(p_new->pass_word,get_info.pass_word);
	    strcpy(p_new->user_name,get_info.user_name);
	    strcpy(p_new->money,get_info.money);

	    if(p->next==NULL)
	    {
		p_new->next=NULL;
		p->next=p_new;
	    }
	    else
	    {
		p_new->next=p->next;
		p->next=p_new;
	    }
	    p=p->next;
	}
	else//结构体访问结束，即结构体已为空或访问到文件尾部
	{
	    fclose(fp);
	    break;
	}
    }

#if 0  //打印链表内容

    p=*head;
    p=p->next;
    while(p)
    {
	printf("p->user_name=%s\n",p->user_name);
	printf("p->pass_word=%s\n",p->pass_word);
	printf("p->money=%s\n",p->money);

	p=p->next;
    }

#endif

}

void read_user_info()
{
    head_car_live=malloc(sizeof(P_INFO_LIVE));
    memset(head_car_live,0,sizeof(P_INFO_LIVE));

    head_man_live=malloc(sizeof(P_INFO_LIVE));
    memset(head_man_live,0,sizeof(P_INFO_LIVE));
    
    link_info(MANPATH,&head_man);
    link_info(CARPATH,&head_car);
}


int main()
{

    system("clear");
    //一般变量
    int i;
    int j;
    int ret;
    int client=0;
    int client_count=0;

    //线程变量
    pthread_t pthid[512];
    DATA d[512];
    
    //套接字变量
    int sfd;
    int cfd[512];
    struct sockaddr_in sin;
    struct sockaddr_in cin[512];
    unsigned int len;
    char buf[1024]={0};

    //epoll变量
    int epoll_instance;
    int nfound;
    struct epoll_event ev,events[20];

    //建立套接字，确定要使用的协议家族
    sfd = socket(AF_INET,SOCK_STREAM,0);
    if(sfd == -1)
    {
	perror("socket");
	return -1;
    }

    read_user_info();//获取帐户信息建立链表

    char ip_address[20]={0};
    Get_IP_addr(ip_address);//获取本地ip地址

    pthread_t pthid_heart;
    pthread_create(&pthid_heart,NULL,heart_time_pack,(void*)&client_count);//心跳包线程
 
    
    //绑定地址和端口
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    if(inet_pton(AF_INET,ip_address,&sin.sin_addr.s_addr) <=0 )
    {
	perror("inet_pton");
	return -1;
    }
    ret = bind(sfd,(struct sockaddr*)&sin,sizeof(sin));
    if(ret == -1)
    {
	perror("bind");
	return -1;
    }

    //监听
    ret = listen(sfd,30);
    if(ret == -1)
    {
	perror("listen");
	return -1;
    }

    //epoll set
    epoll_instance = epoll_create(256);
    if(epoll_instance == -1)
    {
	perror("epoll_create");
	return -1;
    }
    ev.data.fd = sfd;
    ev.events = EPOLLIN|EPOLLET;
    ret = epoll_ctl(epoll_instance, EPOLL_CTL_ADD,sfd,&ev);

    while(1)
    {
	nfound = epoll_wait(epoll_instance,events,20,-1);
	if(nfound < 0)
	{
	    perror("epoll_wait");
	    continue;
	}
	else if(nfound == 0)
	{
	    printf("time out\n");
	    continue;
	}
	else
	{
	    //循环遍历文件描述符号集合
	    for(i=0;i<nfound ;i++)
	    {
		if(events[i].events == EPOLLIN|EPOLLET && events[i].data.fd == sfd)
		{
		    memset(buf,0,1024);
		    if(0==client_count)client=0;
		    client_count++;
		    client++;
		    len = sizeof(cin[client]);
		    cfd[client] = accept(sfd,(struct sockaddr*)&cin[client],&len);
		    sprintf(buf,"新客户端连接，IP地址:%s,端口号:%d",inet_ntoa(cin[client].sin_addr),ntohs(cin[client].sin_port));
		    write(1,"\n",1);
		    write(1,buf,1024);
		    write(1,"\n",1);
		    if(cfd[client] <0)
		    {
			perror("accept");
			client_count--;
			client--;
			continue;
		    }
		    else if(cfd[client]>0)
		    {
			ev.data.fd = cfd[client];
			ev.events = EPOLLIN|EPOLLET;
			epoll_ctl(epoll_instance,EPOLL_CTL_ADD,cfd[client],&ev);
			continue;
		    }
		}//end if(sfd) 
		else if(events[i].events == EPOLLIN|EPOLLET)
		{
		    for(j=0;j<=client;j++)
		    {
			if(events[i].data.fd==cfd[j])
			{

			    memset(d[j].buf,0,1024);
			    memset(buf,0,1024);
			    ret = read(cfd[j],d[j].buf,1024);//读取接收内容
			    if(ret <=0)
			    {
				epoll_ctl(epoll_instance,EPOLL_CTL_DEL,cfd[j],events);	
				printf("有一个客户端断开连接了\n");
				if(client_count<=0)client_count=0;
				else client_count--;
				printf("现有:%d个客户端连接\n",client_count);
			    }
			    else
			    {
				if(0==strncmp(&d[j].buf[2],"heartpack",11));
				else
				{
				    //显示接收到的客户端的ip和端口
				    sprintf(buf,"客户端发来请求，IP地址:%s,端口号:%d",inet_ntoa(cin[j].sin_addr),ntohs(cin[j].sin_port));
				    write(1,buf,1024);
				    write(1,"\n",1);
				}
				d[j].cfd=&cfd[j]; 
				d[j].epoll_instance=&epoll_instance;
				d[j].events=&events[i];
				d[j].cin=&cin[j];

				pthread_create(&pthid[j],NULL,do_for_client,(void*)&d[j]);
			    }
			}
		    }
		}
	    }//end for 
	}//if(n <0)
    }//end while(1)
    close(sfd);
}

